#include "stm32f10x.h"                  // Device header
#include "Time.h"
#include "IR.h"


//红外遥控器按键编码
#define NUM_1 		16753245
#define NUM_2 		16736925
#define NUM_3 		16769565
#define NUM_4 		16720605
#define NUM_5 		16712445
#define NUM_6 		16761405
#define NUM_7 		16769055
#define NUM_8 		16754775
#define NUM_9 		16748655
#define NUM_0 		16750695
#define SIGN_Star	16738455
#define SIGN_Well 	16756815
#define UP 			16718055
#define DOWN 		16730805
#define LEFT		16716015
#define RIGHT 		16734885
#define OK 			16726215
 
/* IRState:状态机变量，根据状态机来编写相应的代码，0表示空闲状态，1表示搜寻起始信号或者重复信号，2表示进行数据解码*/
uint8_t IRState;     
uint8_t IRRepeatFlag;	//重复标记位
uint16_t IR_Time;		//定时器的计数值，因为是72分频，每记一个数就是1us
uint32_t Data;			//用来保存数据
uint8_t pData;			//数据帧的位数
uint8_t DataFlag;		// 数据标记位
 
 
void IR_Init()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;   //上拉输入模式
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	
	/* 配置AFIO */
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);
	EXTI_ClearITPendingBit(EXTI_Line14);
	
	/* 配置EXIT */
	EXTI_InitTypeDef EXIT_InitStructure;
	EXIT_InitStructure.EXTI_Line = EXTI_Line14;				//选择哪条中断线
	EXIT_InitStructure.EXTI_LineCmd = ENABLE;
	EXIT_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;		//中断模式or事件模式，这里选择中断模式
	EXIT_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;	//下降沿
	EXTI_Init(&EXIT_InitStructure);
	
	/* 选择NVIC通道组 */
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	/* 配置NVIC */
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
}
 
uint8_t IR_GetDataFlag()			//获取标记位的函数
{
	if(DataFlag==1)
	{
		DataFlag = 0;				//每次获取到数据后都要将数据标记位清0
		return 1;
	}
	DataFlag = 0;
	return 0;
}
 
uint8_t IR_GetRepeatFlag()			//获取重复标记位函数
{
	if(IRRepeatFlag==1)
	{
		IRRepeatFlag = 0;			//每次获取到重复标记后都要将数据标记位清0
		return 1;
	}
	return 0;
}
 
uint16_t IR_GetCounter()			//获取计数值函数
{
	uint16_t temp;
	Timer_Stop();					//先停止
	temp = Timer_GetCounter();		//获取值
	Timer_Run();					//再开启
	return temp;
}
 
void EXTI15_10_IRQHandler(void)		//在中断函数里进行数据解码
{
	if( EXTI_GetITStatus(EXTI_Line14)==SET)
	{
		if(IRState==0)											//如果状态是0，表示是空闲状态
		{
			Timer_Run();
			IRState = 1;
		}
		else if(IRState==1)
		{
			IR_Time = IR_GetCounter();
			if(IR_Time > 13500-1500 && IR_Time < 13500+1500)	//起始信号
			{
				IRState = 2;
			}
			else if(IR_Time<11250+500 && IR_Time>11250-500)		//重复信号
			{
				IRRepeatFlag=1;
				Timer_Stop();
				IRState = 0;
			}
			else
			{
				IRState = 1;
			}
		}
		else if(IRState==2)
		{
			IR_Time = IR_GetCounter();
			if(IR_Time<1120+500 && IR_Time>1120-500)		//数据0
			{
				Data <<=1;
				Data += 0;
				pData++;
			}
			else if(IR_Time<2250+500 && IR_Time>2250-500)	//数据1
			{
				Data <<=1;
				Data += 1;
				pData++;
			}
			else											//错误数据处理
			{
				Data = 0;
				IRState = 1;
			}
			if(pData >= 32)
			{
				pData = 0;
				DataFlag = 1;
				Timer_Stop();
				IRState=0;
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line14);
	}
}
